using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using Domain.Common;
using Domain.Model;

namespace Domain.Repositories
{
	/// <summary>
	///     Maintains the sessions between contacts.
	/// </summary>
	public class SessionManager : IRepository<Session>
	{
		private readonly ICollection<Session> _sessions = new Collection<Session>();
		private readonly Messenger _messenger;

		// the factory for creating new session object.
		public Session CreateSession()
		{
			var session = new Session(_messenger)
			{
				ID = Guid.NewGuid()
			};

			session.AttachContact(ContactManager.Myself);

			return session;
		}

		public void AttachSession(Session session)
		{
			_sessions.Add(session);
		}

		public void DetachSession(Session session)
		{
			_sessions.Remove(session);
		}

		public Session FindSessionByID(Guid id)
		{
			return _sessions.First(s => s.ID.Equals(id));
		}

		//public ICollection<Session> FindBySpecification(Specification<T> specification)
		//{
		//    var sessions = new Collection<Session>();


		//    return sessions;
		//}

		// Handler for message YouAreInvited
		public void Clone(Session session)
		{
			//TODO: clone a new session.
			//It sends the attendants info except of the invited.
			var s = this.CreateSession();

			s.ID = session.ID;
			foreach (var contact in session.Contacts)
			{
				s.AttachContact(contact);
			}

			this.AttachSession(s);
		}

		// Handler for message SomeoneChanged
		public void ContactInfoChanged(Contact contact)
		{
			//TODO: notifies sessions which the contact attended to update contact info.
			var spec = new Specification<ICollection<Contact>>(cs => cs.Select(c => c.ID).Contains(contact.ID));

			foreach (var session in _sessions.Where(s => spec.IsSatisfiedBy(s.Contacts)))
			{
				session.ContactInfoChanged(contact);
			}
		}
	}
}